#define  _CRT_SECURE_NO_WARNINGS

#include "opencv/cv.h"
#include "opencv2/objdetect/objdetect.hpp"
#include "opencv2/features2d/features2d.hpp"
#include "opencv2/calib3d/calib3d.hpp"
#include "opencv2/nonfree/nonfree.hpp"
#include "opencv2/imgproc/imgproc_c.h"
#include "opencv2/legacy/legacy.hpp"
#include "opencv2/legacy/compat.hpp"
#include "opencv2/highgui/highgui.hpp"


#include "StdAfx.h"
#include "xkRefPoint.h"
#include "xfRefDetectRect.h"


xfRefDetectRect::xfRefDetectRect(void)
{
	m_pRefPoint = (xkRefPoint*)this;

	memset(m_szDetectFile,0,sizeof(m_szDetectFile));
}

xfRefDetectRect::~xfRefDetectRect(void)
{
}


#define REGION_EDEG_OFFSET 2

BOOL CheckRegion( zkDetRect *pDetRect,zkAnalyJudgeRegionCfg *pRegionRect )
{
    if( pDetRect->nPoints != pRegionRect->nPoints ||
		memcmp( pDetRect->xPoint,pRegionRect->xPoint,(sizeof(zkPoint)*pDetRect->nPoints) ) != 0 )
	{
		int i=0;
		
		if( pRegionRect->nPoints < MAX_DEF_POINT )
		{
			for(i=pDetRect->nPoints;i<MAX_DEF_POINT;i++)
			{
				pDetRect->xPoint[i].x = 0;
				pDetRect->xPoint[i].y = 0;
			}
		}

	   	pDetRect->nPoints = pRegionRect->nPoints;
		memcpy( pDetRect->xPoint,pRegionRect->xPoint,(sizeof(zkPoint)*MAX_DEF_POINT) );

		int nMinX=60000,nMaxX=0,nMinY=60000,nMaxY=0;

		for( i=0;i<pDetRect->nPoints;i++ )
		{
			if( nMinX > pDetRect->xPoint[i].x )
			{
				nMinX = pDetRect->xPoint[i].x;
			}
			if( nMaxX < pDetRect->xPoint[i].x )
			{
				nMaxX = pDetRect->xPoint[i].x;
			}
			if( nMinY > pDetRect->xPoint[i].y )
			{
				nMinY = pDetRect->xPoint[i].y;
			}
			if( nMaxY < pDetRect->xPoint[i].y )
			{
				nMaxY = pDetRect->xPoint[i].y;
			}
		}

		pDetRect->x = nMinX - REGION_EDEG_OFFSET;
		pDetRect->y = nMinY - REGION_EDEG_OFFSET;
		pDetRect->w = nMaxX - nMinX + REGION_EDEG_OFFSET*2;
		pDetRect->h = nMaxY - nMinY + REGION_EDEG_OFFSET*2;

		return FALSE;
	}

	return TRUE;
}


int xfRefDetectRect::SetRegion(void *pVoid) 
{
	zkAnalyJudgeRegionCfg *pRegionCfg = (zkAnalyJudgeRegionCfg*)pVoid;
	if( NULL == pRegionCfg )
	{
		return DD_ERR_PARAMETER;
	}

	DWORD dwWidth  = (DWORD)m_pRefPoint->m_ImgBitInfo.nWidth;
	DWORD dwHeight = (DWORD)m_pRefPoint->m_ImgBitInfo.nHeight;
	DWORD dwSize   = dwHeight * dwWidth;
	
	zkAnalyDetRect *pDetect  = &m_xDetectRect;
	zkDetRect      *pDetRect = pDetect->xDetRt;

	int nDetectRtBufSize = 0;

	BOOL bRet = TRUE;
	int i=0;
	for(i=0;i<MAX_DEF_REGION;i++)
	{
        bRet &= CheckRegion( &(pDetRect[i]),&(pRegionCfg[i]) );

		nDetectRtBufSize += (pDetect->xDetRt[i].w * pDetect->xDetRt[i].h ); 
	}
	if( bRet )
	{
		return DD_ERR_SUCCESS;
	}

	pDetect->dwHeight = dwHeight;
	pDetect->dwWidth  = dwWidth;
	pDetect->dwAllDetRectSize = nDetectRtBufSize;

	if( !m_xBuffer.Allocate(nDetectRtBufSize) )
	{
		return DD_ERR_NEWBUFFER;
	}
	m_xBuffer.MemSet();

	int nRtSize      = 0;
	int nDetRtOffset = 0;
	char *pDetRtData = NULL;

	IplImage xImage,*pImgDst;
	memset(&xImage,0,sizeof(IplImage));
	pImgDst = &xImage;
	pImgDst->nSize     = sizeof( IplImage );
	pImgDst->nChannels = 1;
	pImgDst->depth     = IPL_DEPTH_8U;
	pImgDst->align     = CV_DEFAULT_IMAGE_ROW_ALIGN;
	pImgDst->origin    = IPL_ORIGIN_TL;
	
	for(i=0;i<MAX_DEF_REGION;i++)
	{
		nRtSize = pDetRect[i].w * pDetRect[i].h;
		if( nRtSize > 0 )
		{
			pDetRtData = (char*)m_xBuffer.pBuffer + nDetRtOffset;
			nDetRtOffset += nRtSize;

			pImgDst->width         = pDetRect[i].w;
			pImgDst->height        = pDetRect[i].h;
			pImgDst->widthStep     = pImgDst->width  * sizeof(BYTE);
			pImgDst->imageSize     = pImgDst->height * pImgDst->widthStep;
			pImgDst->imageData     = pDetRtData;
			pDetRect[i].pDetRtData = (BYTE*)pDetRtData;

			CalcRegion(&(pDetRect[i]),pImgDst);

// 			char szName[20];
// 			sprintf(szName,"c:\\Rect_%d.bmp",i);
// 			cvSaveImage(szName,pImgDst);
		}
		else
		{
            pDetRect->pDetRtData = NULL;
		}
	}

	return 0;
}

BOOL xfRefDetectRect::CalcRegion( zkDetRect *pDetRect,IplImage *pImgDst)
{
   CvPoint prev_pt,pt;
   prev_pt.x = ( pDetRect->xPoint[0].x - pDetRect->x );
   prev_pt.y = ( pDetRect->xPoint[0].y - pDetRect->y );

   int i=0;
   for( i=1;i<pDetRect->nPoints;i++ )
   {
	   pt.x = ( pDetRect->xPoint[i].x - pDetRect->x );
	   pt.y = ( pDetRect->xPoint[i].y - pDetRect->y );

	   cvLine( pImgDst, prev_pt, pt, cvScalarAll(255), 1, 8, 0 );

	   prev_pt = pt;
   }

   pt.x = ( pDetRect->xPoint[0].x - pDetRect->x );
   pt.y = ( pDetRect->xPoint[0].y - pDetRect->y );
   cvLine( pImgDst, prev_pt, pt, cvScalarAll(255), 1, 8, 0 );

   CvMemStorage* storage = cvCreateMemStorage(0);
   CvSeq* contour = 0;
   int num = cvFindContours(pImgDst, storage, &contour,sizeof(CvContour), CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE);
   for( ; contour != 0; contour = contour->h_next )
   {
	   CvScalar color = CV_RGB(255, 255, 255 );
	   if (cvContourArea(contour) > 20)
	   {
		   cvDrawContours( pImgDst, contour, color, color, 0, CV_FILLED );
	   } 
   }

   return TRUE;
}


#include "DDReadWriteFile.h"

int xfRefDetectRect::SetDetectRegionFile(char *pFileName)
{
	strcpy(m_szDetectFile,pFileName);

	return 0;
}

int xfRefDetectRect::LoadDetectRegion()
{
	int nRet = -1;

	DDReadWriteFile xFile;
	zkAnalyDetRect *pHead = &m_xDetectRect;

	do 
	{
		char *pFileName = m_szDetectFile;

		LONGLONG llFileSize = 0;

		if( 0 != xFile.DDCreateFile(pFileName,TRUE,&llFileSize) )
		{
			nRet = -1;
			break;
		}

		LONGLONG llFileOffset = 0;
		nRet = xFile.DDOperatorFile( (BYTE*)pHead,sizeof(zkAnalyDetRect),&llFileOffset);
		if( nRet != 0)
		{
			break;
		}
		if( !pHead->CheckVersion() )
		{
			nRet = -1;
			break;
		}

		DWORD dwWidth  = pHead->dwWidth;
		DWORD dwHeight = pHead->dwHeight;
		DWORD dwSize   = pHead->dwAllDetRectSize;
		if( !m_xBuffer.Allocate(dwSize) )
		{
			nRet = DD_ERR_NEWBUFFER;
			break;
		}
		BYTE *pBuffer = m_xBuffer.pBuffer;
		nRet = xFile.DDOperatorFile( pBuffer,dwSize,&llFileOffset);
		if( nRet != 0)
		{
			break;
		}

		zkDetRect *pDetRect = pHead->xDetRt;

		int nRtSize      = 0;
		int nDetRtOffset = 0;
		char *pDetRtData = NULL;
		for(int i=0;i<MAX_DEF_REGION;i++)
		{
			nRtSize = pDetRect[i].w * pDetRect[i].h;
			if( nRtSize > 0 )
			{
				pDetRtData = (char*)m_xBuffer.pBuffer + nDetRtOffset;
				nDetRtOffset += nRtSize;
				pDetRect[i].pDetRtData = (BYTE*)pDetRtData;
			}
			else
			{
				pDetRect[i].pDetRtData = NULL;
			}
		}

		return nRet;

	} while (FALSE);

	memset(pHead,0,sizeof(zkAnalyDetRect));//

	return nRet;
}

int xfRefDetectRect::SaveDetectRegion()
{
	int nRet = -1;

	if( NULL == m_xBuffer.pBuffer )
	{
		return DD_ERR_PARAMETER;
	}

	DDReadWriteFile xFile;

	do 
	{
		char *pFileName = m_szDetectFile;

		LONGLONG llFileSize = 0;

		if( 0 != xFile.DDCreateFile(pFileName,FALSE,&llFileSize) )
		{
			nRet = -1;
			break;
		}	

		LONGLONG llFileOffset = 0;

		zkAnalyDetRect *pHead = &m_xDetectRect;
		pHead->dwFileVersion = DD_ANALY_VERSION_2012;
		nRet = xFile.DDOperatorFile( (BYTE*)pHead,sizeof(zkAnalyDetRect),&llFileOffset,FALSE);
		if( nRet != 0)
		{
			break;
		}

		DWORD dwWidth  = pHead->dwWidth;
		DWORD dwHeight = pHead->dwHeight;
		DWORD dwSize   = pHead->dwAllDetRectSize;
		BYTE *pBuffer  = m_xBuffer.pBuffer;

		nRet = xFile.DDOperatorFile( pBuffer,dwSize,&llFileOffset,FALSE);
		if( nRet != 0)
		{
			break;
		}

	} while (FALSE);

	return nRet;
}